import widgets from './widgets'
import WithArrayWidget from './widgets/WithArrayWidget'
import RowLayout from '../RowLayout/index.vue'
import { CirclePlus } from '@element-plus/icons'
import { typeofFn } from '../../utils'
import { Transition } from 'vue'

// 渲染小部件
export const renderItem = (
  { prop, widget, widgetAttrs, options },
  formData
) => {
  const Comp = widgets[widget]

  if (['select', 'radio', 'checkbox'].includes(widget)) {
    return (
      <Comp {...widgetAttrs} v-model={formData[prop]} options={options}></Comp>
    )
  }
  return <Comp {...widgetAttrs} v-model={formData[prop]}></Comp>
}

// 渲染type 为 default 的项
const renderDefault = (
  { labelWidth, itemAttrs, prop, description, ...attrs },
  formData
) => {
  return (
    <ElFormItem labelWidth={labelWidth} {...itemAttrs} prop={prop}>
      <div class={'form-item-content'}>
        <div class={'widget-wrap'}>
          {renderItem({ prop, ...attrs }, formData)}
        </div>
        {description ? <span class="desc-info">{description}</span> : null}
      </div>
    </ElFormItem>
  )
}

// 渲染type 为 object 的项
const renderObject = (
  {
    prop: parentProp,
    itemAttrs = {},
    layout,
    gutter,
    childLabelWidth: labelWidth,
    properties,
    show,
    isToggle,
    toggle = () => {}
  },
  formData
) => {
  if (typeofFn(properties) !== 'object') {
    throw Error(
      `'properties' is not an object, please Check that an 'properties' is written correctly`
    )
  }
  formData =
    typeofFn(formData[parentProp]) === 'object'
      ? formData[parentProp]
      : formData
  return (
    <ElFormItem {...itemAttrs} prop={parentProp}>
      <Transition mode="out-in" name="fade-slide">
        <RowLayout
          layout={layout}
          gutter={gutter}
          class={
            show === undefined || show === true
              ? 'fade-enter-active'
              : 'fade-leave-active'
          }
          style={{
            display: show === undefined || show === true ? 'flex' : 'none'
          }}
        >
          {Object.keys(properties).map((prop) => {
            const item = properties[prop]
            const { type = 'default', ...reset } = item
            if (type === 'default') {
              return renderDefault({ prop, labelWidth, ...reset }, formData)
            } else if (type === 'array') {
              return renderArray({ prop, ...item }, formData)
            } else {
              return renderObject({ prop, ...item }, formData[prop])
            }
          })}
        </RowLayout>
      </Transition>
      {isToggle === true ? (
        <span
          style={{ cursor: 'pointer', color: '#626062' }}
          onClick={() => toggle()}
        >
          {show ? '收缩' : '展开'}
        </span>
      ) : null}
    </ElFormItem>
  )
}

// 渲染type 为 array 的项
const renderArray = (
  { prop, onChange, initialState = '', gutter, itemAttrs, widgetAttrs, schema },
  formData
) => {
  if (!Array.isArray(formData[prop])) {
    formData[prop] = []
  }
  const values = formData[prop]

  // 添加数组的元素
  const handleAdd = () => {
    if (typeof initialState === 'object') {
      values.push(Object.assign({}, initialState))
    } else {
      values.push(initialState)
    }
  }

  const t = () => {
    if (
      typeofFn(initialState) !== 'string' &&
      typeofFn(initialState) !== 'object'
    ) {
      throw Error('initialState must be a string or object')
    }
    if (typeof initialState === 'string') {
      const Comp = widgets['input']
      return (
        <ElFormItem {...itemAttrs} prop={prop}>
          {values.map((item, index) => (
            <WithArrayWidget
              index={index}
              values={values}
              gutter={gutter}
              onChange={onChange}
            >
              {/* v-model={values[index]} 千万别改成 v-model={item}，因为字符串不是引用值，不会产生双向响应*/}
              <Comp {...widgetAttrs} v-model={values[index]}></Comp>
            </WithArrayWidget>
          ))}
          <ElButton type="primary" onClick={handleAdd} icon={CirclePlus}>
            添加
          </ElButton>
        </ElFormItem>
      )
    }
    if (typeof initialState === 'object') {
      if (typeofFn(schema) !== 'object') {
        throw Error(
          `'schema' is not an object,  please Check that an 'schema is not an object,  please Check that an 'schema' is written correctly' is written correctly`
        )
      }
      return (
        <ElFormItem {...itemAttrs} prop={prop}>
          {values.map((item, index) => (
            <WithArrayWidget
              prop={index}
              index={index}
              values={values}
              gutter={gutter}
              onChange={onChange}
            >
              {Object.keys(schema).map((prop) =>
                renderItem({ prop, ...schema[prop] }, item)
              )}
            </WithArrayWidget>
          ))}
          <ElButton onClick={handleAdd}>添加</ElButton>
        </ElFormItem>
      )
    }
  }
  return t()
}
export const renderForm = (formSchema, formData) => {
  return Object.keys(formSchema).map((prop) => {
    const item = formSchema[prop]
    const { type, ...reset } = item
    if (type === 'default') {
      return renderDefault({ prop, ...reset }, formData)
    }

    if (type === 'object') {
      return renderObject({ prop, ...item }, formData)
    }

    if (type === 'array') {
      return renderArray({ prop, ...item }, formData)
    }
  })
}
